
#include "task.hpp"

const int gunm = 3;
Task t;
class EndPoint
{
public:
    EndPoint(int id, int fd)
        : _child_id(id), _write_fd(fd)
    {
        //名字样式 process-0[pid:fd]
        char namebuff[64];
        snprintf(namebuff,sizeof(namebuff),"process-%d[%d:%d]",number++,_child_id,_write_fd);
        processname = namebuff;
    }
    const string &name() const
    {
        return processname;
    }
    ~EndPoint()
    {
    }

public:
    // 子进程pid
    pid_t _child_id;
    // 父进程向管道写的文件描述符
    int _write_fd;
    string processname;
private:
    static int number;
};
int EndPoint::number = 0;

void waitcommand()
{
    while (true)
    {
        int command = 0;
        // 将0号输入流重定向位管道
        int n = read(0, &command, sizeof(int));
        if (n == sizeof(int))
        {
            t.Execute(command);
        }
        else if (n == 0)
        {
            cout<<"父进程让我退出我就退出了"<<getpid()<<endl;
            break;
        }
        else
        {
            break;
        }
    }
}
void creatProcesses(vector<EndPoint> &end_points)
{
    vector<int> fds;
    for (int i = 0; i < gunm; i++)
    {
        int pipefd[2] = {0};
        int n = pipe(pipefd);
        assert(n == 0);
        (void)n;
        pid_t id = fork();
        assert(id != -1);
        if (id == 0)
        {
            // 子进程
            for(auto & fd :fds)
            close(fd);
            
            close(pipefd[1]);

            dup2(pipefd[0], 0);
            waitcommand();
            // 退出关闭读
            close(pipefd[0]);
            exit(0);
        }
        // 父进程
        close(pipefd[0]);

        end_points.push_back(EndPoint(id, pipefd[1]));
        //父进程
        fds.push_back(pipefd[1]);
    }
}
int showBoard()
{
    cout<<"***************************"<<endl;
    cout<<"**     0.执行日志任务     **"<<endl;
    cout<<"**     1.执行数据库任务   **"<<endl;
    cout<<"**     2.执行请求任务     **"<<endl;
    cout<<"**     3.退出            **"<<endl;
    cout<<"***************************"<<endl;
    cout<<"*******4.请选则";
    int command = 0;
    cin >> command;
    return command;

}
void ctrlProcess(const vector<EndPoint>& end_points)
{    
    // 交互式让子进程执行任务
    int num = 0;
    int cnt =0;
    while (true)
    {
        // 1。选择任务
        int command = showBoard();
        if(command == 3) break;
        if(command<0||command>2) continue;
     
        // 2.选择进程
        int index = cnt++;
        cnt %= end_points.size();
        cout<<"选择了进程："<<end_points[index].name()<<"|处理任务："<< command <<endl;

        // 3.下发任务
        write(end_points[index]._write_fd,&command,sizeof(command));
        sleep(1);
    }
}
void waitProcess(const vector<EndPoint>& end_points)
{
    //1.子进程全部退出（父进程关闭写端）
    //for(auto &ep : end_points)
    
    for(int end = end_points.size()-1;end>=0;end--)
    {
        cout<<"父进程让子进程全部退出"<<end_points[end]._child_id<<endl;
        close(end_points[end]._write_fd);
        waitpid(end_points[end]._child_id,nullptr,0);
        cout<<"父进程回收了子进程"<<end_points[end]._child_id<<endl;
    }
    sleep(10);
}
int main()
{
    // 1.先创建控制结构，父进程写入，子进程读取
    vector<EndPoint> end_points;
    creatProcesses(end_points);
    //2.控制进程
    ctrlProcess(end_points);
    //3.处理退出问题
    waitProcess(end_points);


    return 0;
    
}